package com.bigfans.framework.redis;

import java.util.List;
import java.util.Map;
import java.util.Set;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;

/**
 * 
 * @Title:
 * @Description:redis链接实例
 * @author lichong
 * @date 2016年1月28日 上午7:47:12
 * @version V1.0
 */
public class JedisConnection {

	private Transaction tx;
	private Pipeline pipeline;
	private Jedis jedis = null;

	public JedisConnection(Jedis jedis , int dbIndex) {
		this.jedis = jedis;
		jedis.select(dbIndex);
	}
	
	public void openPipeline(){
		pipeline = jedis.pipelined();
	}
	
	public List<Object> closePipeline(boolean returnResult){
		if(returnResult){
			return pipeline.syncAndReturnAll();
		}
		pipeline.sync();
		return null;
	}
	
	public void beginTransaction(){
		tx = jedis.multi();
	}
	
	public void commit(){
		if(tx != null){
			tx.exec();
		}
	}
	
	public void selectDB(int dbIndex){
		jedis.select(dbIndex);
	}
	
	public void flushDB(){
		jedis.flushDB();
	}
	
	public void release(){
		jedis.close();
	}

	public void publish(String channel , String message){
		jedis.publish(channel, message);
	}
	
	public void subscribe(JedisPubSub listener , String... channels){
		jedis.subscribe(listener, channels);
	}
	
	public boolean isPipeline(){
		return this.pipeline != null;
	}
	
	public void expire(final String key , final int timeoutSecs){
		if(isPipeline()){
			pipeline.expire(key, timeoutSecs);
			return;
		}
		jedis.expire(key, timeoutSecs);
	}
	
	/**
	 * 获取数据
	 * 
	 * @param key
	 * @return
	 */
	public String get(final String key) {
		byte[] bytes = get(key.getBytes());
		if(bytes == null){
			return null;
		}
		return new String(get(key.getBytes()));
	}

	/**
	 * 获取数据
	 * 
	 * @param key
	 * @return
	 */
	public byte[] get(final byte[] key) {
		if(isPipeline()){
			pipeline.get(key);
			return null;
		}
		return jedis.get(key);
	}

	public void set(final String key, final String value) {
		set(key.getBytes() , value.getBytes());
	}
	
	public void set(final String key, final String value , int time) {
		set(key.getBytes() , value.getBytes() , time);
	}
	
	public void set(final byte[] key, final byte[] value) {
		if(isPipeline()){
			pipeline.set(key, value);
			return;
		}
		jedis.set(key, value);
	}

	public void set(final byte[] key, final byte[] value, final int time) {
		if(isPipeline()){
			pipeline.set(key, value);
			pipeline.expire(key, time);
			return;
		}
		jedis.set(key, value);
		jedis.expire(key, time);
	}

	public void hset(final byte[] key, final byte[] field, final byte[] value) {
		if(isPipeline()){
			pipeline.hset(key, field, value);
			return;
		}
		jedis.hset(key, field, value);
	}

	public void hset(final String key, final String field, final String value) {
		if(isPipeline()){
			pipeline.hset(key, field, value);
			return;
		}
		jedis.hset(key, field, value);
	}

	/**
	 * 获取数据
	 * 
	 * @param key
	 * @return
	 */
	public String hget(final String key, final String field) {
		if(isPipeline()){
			pipeline.hget(key, field);
			return null;
		}
		return jedis.hget(key, field);
	}

	/**
	 * 获取数据
	 * 
	 * @param key
	 * @return
	 */
	public byte[] hget(final byte[] key, final byte[] field) {
		if(isPipeline()){
			pipeline.hget(key, field);
			return null;
		}
		return jedis.hget(key, field);
	}

	public void hdel(final String key, final String field) {
		hdel(key.getBytes() , field.getBytes());
	}
	
	public void hdel(final byte[] key, final byte[] field) {
		if(isPipeline()){
			pipeline.hdel(key, field);
			return ;
		}
		jedis.hdel(key, field);
	}
	
	public void zadd(final String key , final double score , final String member){
		if(isPipeline()){
			pipeline.zadd(key, score, member);
			return ;
		}
		jedis.zadd(key, score, member);
	}

	public void zincrby(final String key , final double score , final String member){
		if(isPipeline()){
			pipeline.zincrby(key, score, member);
			return ;
		}
		jedis.zincrby(key, score, member);
	}
	
	public void zremrangebyrank(final String key , final long start , final long end){
		if(isPipeline()){
			pipeline.zremrangeByRank(key, start, end);
			return ;
		}
		jedis.zremrangeByRank(key, start, end);
	}
	
	public Set<String> zrangeByScore(final String key , final double min , final double max){
		if(isPipeline()){
			Response<Set<String>> zrangeByScore = pipeline.zrangeByScore(key, min, max);
			return zrangeByScore.get();
		}
		return jedis.zrangeByScore(key, min, max);
	}

	/**
	 * 按照分数从小到大排序
	 * @param key
	 * @param start
	 * @param end
	 * @return
	 */
	public Set<String> zrange(final String key , final int start , final int end){
		if(isPipeline()){
			Response<Set<String>> zrangeByScore = pipeline.zrange(key, start, end);
			return zrangeByScore.get();
		}
		return jedis.zrange(key, start, end);
	}

	/**
	 * 按照分数从大到小排序
	 * @param key
	 * @param start
	 * @param end
	 * @return
	 */
	public Set<String> zrevrange(final String key , final int start , final int end){
		if(isPipeline()){
			Response<Set<String>> zrangeByScore = pipeline.zrevrange(key, start, end);
			return zrangeByScore.get();
		}
		return jedis.zrevrange(key, start, end);
	}

	/**
	 * 存储REDIS队列 顺序存储
	 * 
	 * @param byte[] key reids键名
	 * @param byte[] value 键值
	 */
	public void lpush(final byte[] key, final byte[] value) {
		if(isPipeline()){
			pipeline.lpush(key, value);
			return ;
		}
		jedis.lpush(key, value);
	}
	
	public void lpush(final String key, final String value) {
		lpush(key.getBytes(), value.getBytes());
	}

	/**
	 * 存储REDIS队列 反向存储
	 * 
	 * @param byte[] key reids键名
	 * @param byte[] value 键值
	 */
	public void rpush(final byte[] key, final byte[] value) {
		if(isPipeline()){
			pipeline.rpush(key, value);
			return ;
		}
		jedis.rpush(key, value);
	}
	
	public void rpush(final String key, final String value) {
		rpush(key.getBytes(), value.getBytes());
	}

	/**
	 * 将列表 source 中的最后一个元素(尾元素)弹出，并返回给客户端
	 * 
	 * @param byte[] key reids键名
	 * @param byte[] value 键值
	 */
	public void rpoplpush(final byte[] key, final byte[] destination) {
		if(isPipeline()){
			pipeline.rpoplpush(key, destination);
			return ;
		}
		jedis.rpoplpush(key, destination);
	}

	/**
	 * 获取队列数据
	 * 
	 * @param byte[] key 键名
	 * @return
	 */
	public List<byte[]> lpopList(final byte[] key) {
		if(isPipeline()){
			pipeline.lrange(key, 0, -1);
			return null;
		}
		return jedis.lrange(key, 0, -1);
	}

	/**
	 * 获取队列数据
	 * 
	 * @param byte[] key 键名
	 * @return
	 */
	public byte[] rpop(final byte[] key) {
		if(isPipeline()){
			pipeline.rpop(key);
			return null;
		}
		return jedis.rpop(key);
	}

	public void hmset(final Object key, final Map<String, String> hash) {
		if(isPipeline()){
			pipeline.hmset(key.toString(), hash);
			return;
		}
		jedis.hmset(key.toString(), hash);
	}

	public void hmset(final Object key, final Map<String, String> hash, final int time) {
		if(isPipeline()){
			pipeline.hmset(key.toString(), hash);
			pipeline.expire(key.toString(), time);
			return;
		}
		jedis.hmset(key.toString(), hash);
		jedis.expire(key.toString(), time);
	}

	public List<String> hmget(final Object key, final String... fields) {
		if(isPipeline()){
			pipeline.hmget(key.toString(), fields);
			return null;
		}
		return jedis.hmget(key.toString(), fields);
	}

	public Set<String> hkeys(final String key) {
		if(isPipeline()){
			pipeline.hkeys(key);
			return null;
		}
		return jedis.hkeys(key);
	}
	
	public List<String> hvals(final String key) {
		if(isPipeline()){
			pipeline.hvals(key);
			return null;
		}
		return jedis.hvals(key);
	}

	public List<byte[]> lrange(final byte[] key, final int from, final int to) {
		if(isPipeline()){
			pipeline.lrange(key, from, to);
			return null;
		}
		return jedis.lrange(key, from, to);
	}

	public Map<String, String> hgetAll(final String key) {
		if(isPipeline()){
			pipeline.hgetAll(key);
			return null;
		}
		return jedis.hgetAll(key);
	}
	
	public Map<byte[], byte[]> hgetAll(final byte[] key) {
		if(isPipeline()){
			pipeline.hgetAll(key);
			return null;
		}
		return jedis.hgetAll(key);
	}

	public void del(final String key) {
		del(key.getBytes());
	}
	
	public void del(final byte[] key) {
		if(isPipeline()){
			pipeline.del(key);
			return;
		}
		jedis.del(key);
	}

	public Long llen(final String key) {
		return llen(key.getBytes());
	}
	
	public Long llen(final byte[] key) {
		if(isPipeline()){
			pipeline.llen(key);
			return null;
		}
		return jedis.llen(key);
	}
	
	public Boolean exists(final String key){
		if(isPipeline()){
			pipeline.exists(key);
			return null;
		}
		return jedis.exists(key);
	}
	
	public Long hincrBy(final String key, final String field, final long value) {
		if(isPipeline()){
			pipeline.hincrBy(key , field , value);
			return null;
		}
		return jedis.hincrBy(key , field , value);
	}
}
